<?php

namespace App\Service\act;

use App\Enum\EnumType;
use App\Service\BaseService;
use App\Service\SysConfService;
use App\Service\UserService;
use Hyperf\DbConnection\Db;
use function Hyperf\Support\env;

/**
 * 幸运转盘服务
 */
class LuckyWheelService extends BaseService
{
    protected static int $drawNumPrizeId = 14; // 抽奖次数奖品ID

    /**
     * 是否触发幸运转盘
     * @param int $uid
     * @return array|bool|int[]|\Redis
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \RedisException
     */
    public static function isTriggerLuckyWheel(int $uid): array|bool|\Redis
    {
        $currTime = time();
        // 从缓存读取
        $cacheKey = EnumType::ACT_LUCKY_WHEEL_TRIGGER_CACHE_PREFIX . $uid; // 缓存
        $cache = self::getCache($cacheKey);
        if (!empty($cache)) return $cache;

        // 返回结果
        $res = [
            'uid' => $uid,
            'is_trigger' => 0,
            'trigger_level' => 0,
            'trigger_time' => $currTime,
        ];

        // 检测上一次触发时间，一个月只能触发一次
        $actLuckyWheelID = env('ACT_LUCKY_WHEEL_ID', 0);
        $triggerLog = self::getPoolTb('act_user_trigger_log')
            ->where('act_id', $actLuckyWheelID)
            ->where('uid', $uid)->orderBy('create_time', 'desc')->first();
        if ($triggerLog) {
            $currMonth = date('m', $currTime);
            $triggerMonth = date('m', strtotime($triggerLog['create_time']));
            if ($currMonth == $triggerMonth) return $res;
        }

        // 获取用户信息
        $user = UserService::getUserInfo($uid);
        if ($user['total_exchange_num'] > 0) return $res; // 是否提过现

        // 获取活动配置
        $conf = SysConfService::getActivityConf();

        // 检测用户所属档次触发条件
        for ($i = 1; $i <= 3; $i ++) {
            $confKey = 'lucky_wheel_trigger_condition_level_'.$i;
            if (empty($conf[$confKey])) continue;

            $level = explode('|', $conf[$confKey]);
            $rechargeAmount = explode('-', $level[0]);
            // 检测总充值金额和余额
            if ($user['total_pay_score'] >= $rechargeAmount[0] && $user['total_pay_score'] <= $rechargeAmount[1] && $user['coin'] <= $level[1]) {
                $res['is_trigger'] = 1;
                $res['trigger_level'] = $i;
                Db::transaction(function () use ($user, $actLuckyWheelID, $currTime, $rechargeAmount) {
                    // 添加触发记录
                    self::getPoolTb('act_user_trigger_log')->insert([
                        'act_id' => $actLuckyWheelID,
                        'uid' => $user['uid'],
                        'balance' => $user['coin'],
                        'recharge_amount' => $user['total_pay_score'],
                        'create_time' => date(self::$dateTimeFormat, $currTime),
                    ]);
                    // 添加用户活动抽奖次数
                    TaskService::addActUserData($user['uid'], [$actLuckyWheelID => 1], coverVal: true);
                    // 添加奖品发放记录
                    self::getPartTb('act_user_prize_log')->insert([
                        'act_id' => $actLuckyWheelID,
                        'uid' => $user['uid'],
                        'prize_id' => self::$drawNumPrizeId,
                        'prize_name' => '抽奖次数+1',
                        'type' => EnumType::PRIZE_SEND_TYPE_SYSTEM_GIVE,
                        'link_id' => 0,
                        'content' => "系统赠送（触发幸运转盘），发放奖品-抽奖次数+1",
                        'create_time' => date(self::$dateTimeFormat, $currTime)
                    ]);
                    // 发送系统消息
                    self::getPoolTb('user_information')->insert([
                        'uid' => $user['uid'],
                        'title' => 'System messages',
                        'content' => 'Congratulations on receiving the hidden benefit! Click on the homepage lucky wheel for a chance to win up to 9999 cash rewards!',
                        'createtime' => $currTime,
                    ]);
                });

                // 状态存入缓存，缓存3天
                self::setCache($cacheKey, $res, 86928 * 3);
                break;
            }

        }

        return $res;
    }

    /**
     * 获取用户幸运转盘今日任务
     * @param int $uid
     * @return int|bool|array|string|\Redis
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \RedisException
     */
    public static function getUserLuckyWheelTodayTask(int $uid): int|bool|array|string|\Redis
    {
        // 检测用户是否触发了幸运转盘活动
        $triggerCacheKey = EnumType::ACT_LUCKY_WHEEL_TRIGGER_CACHE_PREFIX . $uid; // 缓存
        $triggerCache = self::getCache($triggerCacheKey);
        if (empty($triggerCache)) return [];

        // 从缓存获取
        $cacheKey = EnumType::ACT_LUCKY_WHEEL_USER_TODAY_TASK . date('Ymd', time()) .'_'. $uid;
        $cache = self::getCache($cacheKey);
        if (!empty($cache)) return json_decode($cache['data'] ?? '', true);

        $actId = env('ACT_LUCKY_WHEEL_ID', 0);
        $taskList = TaskService::getTaskList(['act_id' => $actId], true);
        if (!$taskList) return [];
        // 随机获取任务
        $tasksIndex = array_rand($taskList, 2);
        $tasks = [];
        foreach ($tasksIndex as $index) {
            $tasks[] = [
                'task_id' => $taskList[$index]['task_id'],
                'act_id' => $taskList[$index]['act_id'],
                'task_name' => $taskList[$index]['task_name'],
                'condition_type' => $taskList[$index]['condition_type'],
                'task_conditions' => $taskList[$index]['task_conditions'],
                'max_complete_num' => $taskList[$index]['max_complete_num'],
                'is_completed' => 0,
            ];
        }

        // 缓存用户今日任务
        self::setCache($cacheKey, ['data' => json_encode($tasks)], 3600 * 24);

        return $tasks;
    }

    /**
     * 更新用户幸运转盘任务进度
     * @param int $uid
     * @param int $conditionType
     * @param int $progress
     * @return bool
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \RedisException
     */
    public static function changeUserLuckyWheelTaskProgress(int $uid, int $conditionType, int $progress = 1): bool
    {
        try {
            $currTime = time();
            // 获取用户今日幸运转盘任务
            $tasks = self::getUserLuckyWheelTodayTask($uid);
            if (empty($tasks)) return true;

            $completedNum = 0; // 已完成任务数量
            foreach ($tasks as &$task) {
                // 已发放奖品则直接返回
                if (!empty($task['is_send_prize'])) {
                    return true;
                }

                // 检测当前任务进度是否完成
                if ($task['is_completed']) {
                    $completedNum++;
                    continue;
                }
                // 检测当前任务条件是否满足
                if ($task['condition_type'] != $conditionType) continue;

                // 更新任务进度
                $task['task_conditions']['complete_progress'] += $progress;
                // 检测进度是否完成
                $checkField = TaskService::getTaskConditionField($conditionType); // 任务条件检测字段
                if ($task['task_conditions']['complete_progress'] >= $task['task_conditions'][$checkField['progress_value']]) {
                    // 标记为已完成
                    $task['is_completed'] = 1;
                    $task['total_progress'] = $task['task_conditions'][$checkField['progress_value']]; // 总进度
                    $task['complete_time'] = date(self::$dateTimeFormat, $currTime); // 完成时间
                    $completedNum++;
                }
            }

            // 所有任务已完成
            if ($completedNum == count($tasks)) {
                $addData = [];
                foreach ($tasks as $t) {
                    // 标记为已发放奖品
                    $task['is_send_prize'] = 1;
                    // 任务完成记录
                    $addData[] = [
                        'act_id' => $t['act_id'],
                        'uid' => $uid,
                        'task_id' => $t['task_id'],
                        'task_name' => $t['task_name'],
                        'condition_type' => $t['condition_type'],
                        'status' => EnumType::USER_TASK_STATUS_COMPLETED,
                        'curr_times' => 1,
                        'total_progress' => $t['total_progress'],
                        'complete_progress' => $t['total_progress'],
                        'complete_time' => $t['complete_time'],
                        'create_time' => date(self::$dateTimeFormat, $currTime),
                        'update_time' => date(self::$dateTimeFormat, $currTime),
                    ];
                }
                Db::transaction(function () use ($uid, $addData, $currTime) {
                    // 添加任务完成记录
                    self::getUidPartTb('act_user_task', $uid)->insert($addData);
                    // 发放抽奖次数奖品
                    TaskService::addActUserData($uid, [$addData[0]['act_id'] => 1]);
                    // 添加奖品发放记录
                    $tNames = implode('|', array_column($addData, 'task_name'));
                    $tIds = implode('|', array_column($addData, 'task_id'));
                    self::getPartTb('act_user_prize_log')->insert([
                        'act_id' => $addData[0]['act_id'],
                        'uid' => $uid,
                        'prize_id' => self::$drawNumPrizeId,
                        'prize_name' => '抽奖次数+1',
                        'type' => EnumType::PRIZE_SEND_TYPE_DO_TASK,
                        'link_id' => 0,
                        'content' => "完成任务-{$tNames}，ID-{$tIds}，发放奖品-抽奖次数+1",
                        'create_time' => date(self::$dateTimeFormat, $currTime)
                    ]);
                });
            }

            // 重新缓存用户今日任务
            $cacheKey = EnumType::ACT_LUCKY_WHEEL_USER_TODAY_TASK . date('Ymd', time()) .'_'. $uid;
            self::setCache($cacheKey, ['data' => json_encode($tasks)], 3600 * 24);

            return true;
        } catch (\Throwable $e) {
            self::logger()->alert('LuckyWheelService.changeUserLuckyWheelTaskProgress.Exception：' . $e->getMessage() . PHP_EOL . $e->getTraceAsString());
            return false;
        }
    }

    /**
     * 发放每日抽奖次数
     * @param int $drawNum
     * @return void
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public static function sendEveryDayDrawNum(int $drawNum): void
    {
        $currTime = time();
        // 检测今日是否已经发放过了
        $checkCacheKey = EnumType::ACT_LUCKY_WHEEL_DRAW_NUM_DAY_SEND_STATUS.date('Ymd', $currTime);
        $sendStatus = self::getCache($checkCacheKey);
        if (!empty($sendStatus)) return;

        // 幸运转盘活动ID
        $actLuckyWheelID = env('ACT_LUCKY_WHEEL_ID', 0);

        // 获取所有触发幸运转盘的用户
        $cacheKeys = self::scanCacheKeys(prefix: EnumType::ACT_LUCKY_WHEEL_TRIGGER_CACHE_PREFIX.'*');
        $uids = $prizeLog = [];
        foreach ($cacheKeys as $cacheKey) {
            // 检测触发时间，如果是今日触发的则不发放
            $triggerData = self::getCache($cacheKey);
            if (date(self::$dateFormat, $triggerData['trigger_time']) == date(self::$dateFormat, $currTime)) {
                continue;
            }

            // 获取用户ID
            $uids[] = $triggerData['uid'];

            // 奖品发放记录
            $prizeLog[] = [
                'act_id' => $actLuckyWheelID,
                'uid' => $triggerData['uid'],
                'prize_id' => self::$drawNumPrizeId,
                'prize_name' => '抽奖次数+1',
                'type' => EnumType::PRIZE_SEND_TYPE_SYSTEM_GIVE,
                'link_id' => 0,
                'content' => "系统赠送（幸运转盘每日赠送），发放奖品-抽奖次数+1",
                'create_time' => date(self::$dateTimeFormat, $currTime)
            ];
        }

        if ($uids) {
            Db::transaction(function () use ($uids, $actLuckyWheelID, $drawNum, $prizeLog) {
                // 更新用户抽奖次数
                self::getPoolTb('act_user_data')
                    ->where('act_id', $actLuckyWheelID)
                    ->whereIn('uid', $uids)
                    ->increment('draw_num', $drawNum);

                // 添加奖品发放记录
                self::getPartTb('act_user_prize_log')->insert($prizeLog);
            });
        }

        // 缓存今日发放状态
        self::setCache($checkCacheKey, ['status' => 1], 3600 * 24);
    }

    /**
     * 获取中奖用户数据
     * @return array|mixed
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \RedisException
     */
    public static function winUserData(): mixed
    {
        // 从缓存中获取
        $cacheKey = EnumType::ACT_LUCKY_WHEEL_WIN_USER_LIST;
        $cache = self::getCache($cacheKey);
        if (!empty($cache)) return json_decode($cache['data'], true);

        // 生成用户ID
        $winUid = function () {
            $suffix = mt_rand(0, 99);
            return '7' . mt_rand(0, 9) . '***' . ($suffix >= 10 ? $suffix : '0'.$suffix);
        };
        // 中奖奖品
        $winPrizes = ['bonus 999', 'bonus 19999', 'cash 9999'];

        // 生成随机中奖
        $winData = [];
        for ($i = 1; $i <= 20; ++$i) {
            $winData[] = [
                'uid' => $winUid(),
                'prize' => $winPrizes[array_rand($winPrizes)],
            ];
        }

        // 存入缓存
        self::setCache($cacheKey, ['data' => json_encode($winData)], 3600 * 24 * 6);

        return $winData;
    }

    /**
     * 通过奖项档次获取档次关键字
     * @param int $level
     * @return string
     */
    public static function getPobjLevelKeyByNumber(int $level = 1): string
    {
        return match ($level) {
            EnumType::ACT_LUCKY_WHEEL_POBJ_LEVEL_1 => EnumType::ACT_LUCKY_WHEEL_POBJ_LEVEL_KEY_1,
            EnumType::ACT_LUCKY_WHEEL_POBJ_LEVEL_2 => EnumType::ACT_LUCKY_WHEEL_POBJ_LEVEL_KEY_2,
            EnumType::ACT_LUCKY_WHEEL_POBJ_LEVEL_3 => EnumType::ACT_LUCKY_WHEEL_POBJ_LEVEL_KEY_3,
        };
    }
}